package com.cizzy.favorite.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cizzy.favorite.entity.Collect;
import com.cizzy.favorite.entity.vo.CollectRequest;
import com.cizzy.favorite.feign.UserFeign;
import com.cizzy.favorite.feign.VideoFeign;
import com.cizzy.favorite.common.Result;
import com.cizzy.favorite.common.UserIdHolder;
import com.cizzy.favorite.entity.Collect;
import com.cizzy.favorite.entity.dto.VideoDTO;
import com.cizzy.favorite.mapper.CollectMapper;
import com.cizzy.favorite.mapper.CollectMapper;
import com.cizzy.favorite.service.ICollectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.cizzy.favorite.config.CizzyFinal.COLLECT_LOCK;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author crissy-月下闲人
 * @since 2023-11-03
 */
@Service
public class CollectServiceImpl extends ServiceImpl<CollectMapper, Collect> implements ICollectService {
    @Resource
    private VideoFeign videoFeign;

    @Resource
    private UserFeign userFeign;

    @Resource
    private CollectMapper collectMapper;

    @Resource
    private RedissonClient redissonClient;

    @GlobalTransactional
    @Override
    public synchronized Result<Collect> createCollect(CollectRequest collectRequest) {
        RLock lock = redissonClient.getLock(COLLECT_LOCK);
        lock.lock();
        Long userId = collectRequest.getUserId();
        Long videoId = collectRequest.getVideoId();
        if(userId == null || videoId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Collect> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId).eq("video_id", videoId);
        boolean exist = collectMapper.exists(wrapper);
        Collect collect = new Collect(userId, videoId);
        if (BooleanUtil.isFalse(exist)) {
            collectMapper.insert(collect);
//            userFeign.addUserCountById("collect_count", userId, 1);
//            videoFeign.addVideoCountById("collect_count", videoId, 1);
        }
        lock.unlock();
        if(BooleanUtil.isTrue(exist)) {
            return Result.error("收藏失败");
        } else {
            return Result.success(collect);
        }
    }

    @GlobalTransactional
    @Override
    public Result<Collect> cancelCollect(CollectRequest collectRequest) {
        RLock lock = redissonClient.getLock(COLLECT_LOCK);
        lock.lock();
        Long userId = collectRequest.getUserId();
        Long videoId = collectRequest.getVideoId();
        if(userId == null || videoId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Collect> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId).eq("video_id", videoId);
        boolean exist = collectMapper.exists(queryWrapper);
        Collect collect = new Collect(userId, videoId);
        if (BooleanUtil.isTrue(exist)) {
            collectMapper.delete(queryWrapper);
//            userFeign.addUserCountById("collect_count", userId, -1);
//            videoFeign.addVideoCountById("collect_count", videoId, -1);
        }
        lock.unlock();
        if(BooleanUtil.isTrue(exist)) {
            return Result.error("取消收藏失败");
        } else {
            return Result.success(collect);
        }
    }

    @Override
    public Result<Boolean> isCollectd(Long userId, Long videoId) {
        if(userId == null || videoId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Collect> queryWrapper = new QueryWrapper<Collect>().
                eq("user_id", userId).eq("video_id", videoId);
        return Result.success(BooleanUtil.isTrue(collectMapper.exists(queryWrapper)));
    }

    @Override
    public Result<List<VideoDTO>> getCollectById(Long userId) {
        if(userId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Collect> queryWrapper = new QueryWrapper<Collect>().eq("user_id", userId);
        List<Collect> collectList = collectMapper.selectList(queryWrapper);
        if(collectList == null) {
            return Result.error("收藏列表查询失败");
        }
        List<Long> videoIdList = collectList.stream().map(Collect::getVideoId).toList();
        List<VideoDTO> videoDTOList = videoFeign.getVideoListByIds(videoIdList).getData();
        if(videoDTOList == null) {
            return Result.error("收藏列表查询失败");
        }
        return Result.success(videoDTOList);
    }

    @Override
    public Result<List<VideoDTO>> getCollectPageById(Long userId, Integer page, Integer pageSize) {
        if(userId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Collect> queryWrapper = new QueryWrapper<Collect>().
                eq("user_id", userId).last(String.format("LIMIT %d,%d", (page-1) * pageSize,page * pageSize));
        List<Collect> collectList = collectMapper.selectList(queryWrapper);
        if(collectList == null) {
            return Result.error("收藏列表查询失败");
        }
        List<Long> videoIdList = collectList.stream().map(Collect::getVideoId).toList();
        List<VideoDTO> videoDTOList = videoFeign.getVideoListByIds(videoIdList).getData();
        if(videoDTOList == null) {
            return Result.error("收藏列表查询失败");
        }
        return Result.success(videoDTOList);
    }

    @Override
    public Result<String> toCollect(Long id) {
        Long userId = UserIdHolder.getUserId();
        QueryWrapper<Collect> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId).eq("video_id", id);
        boolean exists = collectMapper.exists(queryWrapper);
        if (BooleanUtil.isFalse(exists)) {
            collectMapper.insert(new Collect(userId, id));
            //TODO 远程调用视频微服务

            return Result.success("收藏成功!", null);
        }
        collectMapper.delete(queryWrapper);
        //TODO 远程调用视频微服务

        return Result.success("取消收藏成功!", null);
    }

    @Override
    public Result<List<VideoDTO>> getCollectList() {
        Long userId = UserIdHolder.getUserId();
        List<Long> list = collectMapper.selectCollectList(userId);
        if (CollectionUtil.isNotEmpty(list)) {
            return videoFeign.getVideoListByIds(list);
        }
        return Result.success(null);
    }
}
